Skip to main content
Version: 1.0.0

Creating histograms in Muze

Histogram is a graphical display of data using bars of different heights.It is similar to a Bar Chart but a histogram groups numbers into ranges .The height of each bar shows how many fall into each range which help us to decide what ranges to use.

Lets prepare our data

The data is as:

[
  {
    "delay": 20,
    "distance": 570,
    "time": 6.833333333333333
  },
  {
    "delay": 7,
    "distance": 588,
    "time": 6.833333333333333
  },
  {
    "delay": 16,
    "distance": 590,
    "time": 6.883333333333333
  },
  {
    "delay": -19,
    "distance": 1797,
    "time": 6.916666666666667
  }
]

We will create a histogram illustrating the number of flights vs their delay.

Let's create a Datamodel instance from the raw data and some bins depicting the delay intervals.

const { muze } = viz;

const DelayField = "delay";
const DistanceField = "distance";
const TimeField = "time";

const data = [
  {
    delay: 20,
    distance: 570,
    time: 6.833333333333333,
  },
  {
    delay: 7,
    distance: 588,
    time: 6.833333333333333,
  },
  {
    delay: 16,
    distance: 590,
    time: 6.883333333333333,
  },
  {
    delay: -19,
    distance: 1797,
    time: 6.916666666666667,
  },
  {
    delay: -28,
    distance: 1864,
    time: 6.916666666666667,
  },
  {
    delay: -10,
    distance: 1481,
    time: 7,
  },
  {
    delay: -10,
    distance: 361,
    time: 7,
  },
  {
    delay: -28,
    distance: 1235,
    time: 7,
  },
  {
    delay: -3,
    distance: 256,
    time: 7,
  },
  {
    delay: -3,
    distance: 588,
    time: 7,
  },
  {
    delay: -4,
    distance: 423,
    time: 7,
  },
  {
    delay: -4,
    distance: 612,
    time: 7,
  },
  {
    delay: -5,
    distance: 1090,
    time: 7,
  },
  {
    delay: -5,
    distance: 296,
    time: 7,
  },
  {
    delay: 25,
    distance: 369,
    time: 2,
  },
  {
    delay: 22,
    distance: 110,
    time: 6,
  },
  {
    delay: 29,
    distance: 345,
    time: 7,
  },
  {
    delay: 33,
    distance: 407,
    time: 7,
  },
  {
    delay: -6,
    distance: 325,
    time: 7,
  },
  {
    delay: -7,
    distance: 236,
    time: 7,
  },
  {
    delay: 0,
    distance: 223,
    time: 7,
  },
  {
    delay: 0,
    distance: 303,
    time: 7,
  },
];

const schema = [
  {
    name: DelayField,
    type: "measure",
  },
  {
    name: DistanceField,
    type: "measure",
  },
  {
    name: TimeField,
    type: "measure",
  },
];

const formattedData = muze.DataModel.loadDataSync(data, schema);
let rootData = new muze.DataModel(formattedData);

// Bins
const bins = new Array(200)
  .fill()
  .map((d, i) => i - 60)
  .map((d, i) => [d * 10, (d + 1) * 10]);

Then lets create a new variable in our datamodel instance for the bins:

const DelayRangeField = 'delay_range';

const binnedDM = rootData.calculateVariable(
  {
      name: DelayRangeField,
      type: 'dimension'
  },
  [DelayField], 
  (no) => {
    const bin = bins.find(range => no >= range[0] && no <= range[1]);
    return bin ? bin.join(' - ') : undefined;
  };
);

Add a counter for each flight occurrence in each bin:

const FlightsField = "#Flights";

const dm = binnedDM.calculateVariable(
  {
    name: FlightsField,
    type: "measure",
  },
  [DelayField],
  () => 1,
);

Let's prepare our canvas:

const DelayLabelText = "Delay";

muze
  .canvas()
  .rows([FlightsField])
  .columns([DelayRangeField])
  .config({
    axes: {
      x: {
        padding: 0,
        name: DelayLabelText,
        tickFormat: (val) => val.rawValue.split(" - ")[0],
      },
      y: {
        show: false,
        numberOfTicks: 5,
      },
    },
    border: {
      // Hide the layout borders for better visibility
      showValueBorders: {
        left: false,
        bottom: false,
      },
    },
    sort: {
      [DelayRangeField]: (a, b) => {
        const [a1, a2] = a
          .split(" - ")
          .filter((d) => d)
          .map(Number);
        const [b1, b2] = b
          .split(" - ")
          .filter((d) => d)
          .map(Number);
        return a1 - b1;
      },
    },
  })
  .layers([
    {
      mark: "bar",
      transition: {
        disabled: true,
      },
      encoding: {
        strokeWidth: {
          value: "1px",
        },
      },
      interaction: {
        highlight: {
          style: {
            "stroke-width": "2px",
          },
        },
      },
      className: "histogram-bar",
    },
  ])
  .title("Airline arrival delay")
  .data(dm)
  .width(650)
  .height(500)
  .mount("#chart");